#ifndef __WX_FTP_H__
#define __WX_FTP_H__

#include "wx/defs.h"
#include "wx/sckaddr.h"
#include "wx/protocol/protocol.h"
#include "wx/url.h"

class wxFTP : public wxProtocol {
  public:
    enum TransferMode {
      NONE,       // not set by user explicitly
      ASCII,
      BINARY
    };

    wxFTP();
    virtual ~wxFTP();

    // Connecting and disconnecting
    void SetUser( const wxString& user ) { m_user = user; }
    void SetPassword( const wxString& passwd ) { m_passwd = passwd; }

    bool Connect( wxSockAddress& addr, bool wait = true );
    bool Connect( const wxString& host );

    // disconnect
    virtual bool Close();

    // Parameters set up

    // set transfer mode now
    void SetPassive( bool pasv ) { m_bPassive = pasv; }
    void SetDefaultTimeout( wxUint32 Value );
    bool SetBinary() { return SetTransferMode( BINARY ); }
    bool SetAscii() { return SetTransferMode( ASCII ); }
    bool SetTransferMode( TransferMode mode );

    // Generic FTP interface

    // the error code
    virtual wxProtocolError GetError() { return m_lastError; }

    // the last FTP server reply
    const wxString& GetLastResult() { return m_lastResult; }

    // send any FTP command (should be full FTP command line but without
    // trailing "\r\n") and return its return code
    char SendCommand( const wxString& command );

    // check that the command returned the given code
    bool CheckCommand( const wxString& command, char expectedReturn ) {
      return SendCommand( command ) == expectedReturn;
    }

    // Filesystem commands
    bool ChDir( const wxString& dir );
    bool MkDir( const wxString& dir );
    bool RmDir( const wxString& dir );
    wxString Pwd();
    bool Rename( const wxString& src, const wxString& dst );
    bool RmFile( const wxString& path );
    int GetFileSize( const wxString& fileName );

    // Check to see if a file exists in the current dir
    bool FileExists( const wxString& fileName );

    // Download methods
    bool Abort();

    virtual wxInputStream *GetInputStream( const wxString& path );
    virtual wxOutputStream *GetOutputStream( const wxString& path );

    // Directory listing

    // get the list of full filenames, the format is fixed: one file name per
    // line
    bool GetFilesList( wxArrayString& files,
                       const wxString& wildcard = wxEmptyString ) {
      return GetList( files, wildcard, false );
    }

    // get a directory list in server dependent format - this can be shown
    // directly to the user
    bool GetDirList( wxArrayString& files,
                     const wxString& wildcard = wxEmptyString ) {
      return GetList( files, wildcard, true );
    }

    // equivalent to either GetFilesList() (default) or GetDirList()
    bool GetList( wxArrayString& files,
                  const wxString& wildcard = wxEmptyString,
                  bool details = false );

  protected:
    // this executes a simple ftp command with the given argument and returns
    // true if it its return code starts with '2'
    bool DoSimpleCommand( const wxChar *command,
                          const wxString& arg = wxEmptyString );

    // get the server reply, return the first character of the reply code,
    // '1'..'5' for normal FTP replies, 0 (*not* '0') if an error occurred
    char GetResult();

    // check that the result is equal to expected value
    bool CheckResult( char ch ) { return GetResult() == ch; }

    // return the socket to be used, Passive/Active versions are used only by
    // GetPort()
    wxSocketBase *GetPort();
    wxSocketBase *GetPassivePort();
    wxSocketBase *GetActivePort();
    wxString GetPortCmdArgument( const wxIPV4address& Local, const wxIPV4address& New );
    wxSocketBase *AcceptIfActive( wxSocketBase *sock );
    wxString m_user,m_passwd;
    wxString m_lastResult;
    wxProtocolError m_lastError;
    bool m_streaming;
    TransferMode m_currentTransfermode;
    friend class wxInputFTPStream;
    friend class wxOutputFTPStream;
    bool            m_bPassive;
    wxUint32        m_uiDefaultTimeout;
    bool            m_bEncounteredError;
    DECLARE_DYNAMIC_CLASS_NO_COPY( wxFTP )
    DECLARE_PROTOCOL( wxFTP )
};

#define FTP_TRACE_MASK wxT("ftp")

#endif // __WX_FTP_H__
